package cv

import (
	"dustbe/util"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"os/exec"
	"time"

	"github.com/gin-gonic/gin"
)

var tempManager = make(map[string]map[string]bool)

func SR(c *gin.Context) {
	// 一定要先解析，否则绑定失败会改写Content-Type导致一系列莫名其妙的bug
	postData := make(gin.H)
	c.BindJSON(&postData)
	if postData["image"] == nil || postData["id"] == nil {
		c.JSON(4002, gin.H{"msg": "参数请求错误"})
		return
	}

	// 大于20个文件就删除
	allFiles, err := ioutil.ReadDir(cachePath)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "msg": "无法打开本地文件"})
		return
	}
	if len(allFiles) > 20 {
		os.RemoveAll(cachePath)
		os.MkdirAll(cachePath, 0777)
	}

	decoder := base64.StdEncoding
	base64String := postData["image"].(string)
	if len(base64String) < 12 {
		c.JSON(http.StatusOK, gin.H{"code": 4002, "msg": "输入图像base64编码有误"})
	}

	imgBase64, imgType := util.TransImageURL(base64String)
	data, err := decoder.DecodeString(imgBase64)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "msg": err})
	}

	imagePath := fmt.Sprintf("%s/%s.%s", cachePath, postData["id"].(string), imgType)
	fp, _ := os.OpenFile(imagePath, os.O_RDWR|os.O_CREATE, os.ModePerm)
	defer fp.Close()
	fp.Write(data)

	// 创建图像转换的上下文
	subset := map[string]bool{}
	tempManager[postData["id"].(string)] = subset
	outputImagePath := fmt.Sprintf("%s/%s.out.%s", cachePath, postData["id"].(string), imgType)
	tempFolderPath := cachePath + "/" + postData["id"].(string)
	// 开始进行转换
	args := []string{
		srLaunchFile,
		"-m " + srModelPath,
		"-d cpu",
		"-i " + imagePath,
		"-o " + outputImagePath,
		"-t " + tempFolderPath,
	}

	// 开启新的线程进程
	go func() {
		cmd := exec.Command(python, args...)
		err = cmd.Run()
	}()

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"data": gin.H{
			"type":    imgType,
			"percent": 0.05,
		},
	})
}

func SRQuery(c *gin.Context) {
	imgID := c.Query("id")
	imgType := c.Query("type")
	// 检查原本的图片是否存在，不存在说明被干掉了
	orginImagePath := fmt.Sprintf("%s/%s.%s", cachePath, imgID, imgType)
	orginImageExist, _ := util.CheckFilePath(orginImagePath)
	if !orginImageExist {
		c.JSON(http.StatusOK, gin.H{
			"code": 200,
			"data": gin.H{
				"base64":  "",
				"type":    imgType,
				"fin":     false,
				"killed":  true,
				"percent": 0,
			},
		})
		return
	}

	// 默认得到的图片为 id.out.ext
	targetImagePath := fmt.Sprintf("%s/%s.out.%s", cachePath, imgID, imgType)
	// 先尝试取寻找目标文件
	targetImageExist, _ := util.CheckFilePath(targetImagePath)
	if targetImageExist {
		picBytes, _ := ioutil.ReadFile(targetImagePath)
		c.JSON(http.StatusOK, gin.H{
			"code": 200,
			"data": gin.H{
				"base64":  picBytes,
				"type":    imgType,
				"fin":     true,
				"killed":  false,
				"percent": 1.0,
			},
		})
		// 清除上下文
		go func() {
			time.Sleep(3)
			os.RemoveAll(cachePath + "/" + imgID)
			os.Remove(cachePath + "/" + imgID + "." + imgType)
			os.Remove(cachePath + "/" + imgID + ".out." + imgType)
			delete(tempManager, imgID)
		}()
		return
	} else {
		// 更新缓存列表，如果有新的图片，就返回新的
		tempDirPath := cachePath + "/" + imgID
		newFile := ""
		tempDir, _ := ioutil.ReadDir(tempDirPath)
		for _, file := range tempDir {
			if _, ok := tempManager[imgID][file.Name()]; !ok {
				tempManager[imgID][file.Name()] = true
				newFile = file.Name()
			}
		}
		if len(newFile) > 0 {
			tempImgPath := tempDirPath + "/" + newFile
			picBytes, _ := ioutil.ReadFile(tempImgPath)
			precent := float32(len(tempManager[imgID])) / float32(srStageNum)
			c.JSON(http.StatusOK, gin.H{
				"code": 200,
				"data": gin.H{
					"base64":  picBytes,
					"type":    imgType,
					"fin":     false,
					"killed":  false,
					"percent": precent,
				},
			})
			return
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"data": gin.H{
			"code":    200,
			"base64":  "",
			"type":    "",
			"fin":     false,
			"killed":  false,
			"percent": 0.05,
		},
	})
}
